﻿ 
using Microsoft.Extensions.Caching.Distributed;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//using System.Runtime.Caching;
namespace XW.Utils
{
    public static class CacheHelper
    {
        private static readonly string _KEYCOLLECTION = "___all_keys";
        private static readonly IDistributedCache _cache = new NullDistributedCache();
        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T Get<T>(string key)
        {
            return JsonHelper.ToObject<T>(GetString(key));
        }

        public static bool Exist(string key)
        {
            var v = Cache.Get(key);
            if (v == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetString(string key)
        {
            return Cache.GetString(key);
        }
        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void Set<T>(string key, T value)
        {
            SetString(key, JsonHelper.ToJson(value));
        }
        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="opt"></param>
        public static void Set<T>(string key, T value, DistributedCacheEntryOptions opt)
        {
            SetString(key, JsonHelper.ToJson(value), opt);
        }
        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void SetString(string key, string value)
        {
            SetString(key, value, new DistributedCacheEntryOptions());
        }
        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="opt"></param>
        public static void SetString(string key, string value, DistributedCacheEntryOptions opt)
        {
            Cache.SetString(key, value, opt);
            SyncAllKeys(key);
        }


        private static IDistributedCache Cache
        {
            get
            {
                var cache = SXHttpContext.GetService<IDistributedCache>();
                if (cache == null)
                {
                    return _cache;
                }
                return cache;
            }
        }

        private static void SyncAllKeys(string key)
        {
            if (key != _KEYCOLLECTION)
            {
                var _all_keys = Get<List<string>>(_KEYCOLLECTION) ?? new List<string>();
                if (!_all_keys.Contains(key))
                {
                    _all_keys.Add(key);
                    Set(_KEYCOLLECTION, _all_keys, new DistributedCacheEntryOptions() { AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(2) });
                }
            }
        }
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="key"></param>
        public static void Remove(string key)
        {
            Cache.Remove(key);
        }
        /// <summary>
        /// 删除包含
        /// </summary>
        /// <param name="key"></param>
        public static void RemoveByContains(string containKey)
        {
            var _all_keys = Get<List<string>>(_KEYCOLLECTION) ?? new List<string>();
            if (_all_keys.Count > 0)
            {
                for (int i = _all_keys.Count - 1; i >= 0; i--)
                {
                    string key = _all_keys[i];
                    if (key.ToUpper() == (containKey.ToUpper()))
                    {
                        Cache.Remove(key);
                        _all_keys.RemoveAt(i);
                    }
                }
            }
            Set(_KEYCOLLECTION, _all_keys, new DistributedCacheEntryOptions() { AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(2) });
        }

        public static bool ContainsKey(string containKey) {

            var _all_keys = Get<List<string>>(_KEYCOLLECTION) ?? new List<string>();
            if (_all_keys.Count > 0)
            {
                for (int i = _all_keys.Count - 1; i >= 0; i--)
                {
                    string key = _all_keys[i];
                    if (key.ToUpper() == (containKey.ToUpper()))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        /// <summary>
        /// 删除前缀
        /// </summary>
        /// <param name="key"></param>
        public static void RemoveByStartsWith(string preKey)
        {
            var _all_keys = Get<List<string>>(_KEYCOLLECTION) ?? new List<string>();
            if (_all_keys.Count > 0)
            {
                for (int i = _all_keys.Count - 1; i >= 0; i--)
                {
                    string key = _all_keys[i];
                    if (key.ToUpper().StartsWith(preKey.ToUpper()))
                    {
                        Cache.Remove(key);
                        _all_keys.RemoveAt(i);
                    }
                }
            }
            Set(_KEYCOLLECTION, _all_keys, new DistributedCacheEntryOptions() { AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(2) });
        }
        /// <summary>
        /// 清除所有缓存
        /// </summary>
        public static void Clear()
        {
            var _all_keys = Get<List<string>>(_KEYCOLLECTION) ?? new List<string>();
            foreach (string key in _all_keys)
            {
                Remove(key);
            }
            Set(_KEYCOLLECTION, new List<string>(), new DistributedCacheEntryOptions() { AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(2) });
        }


        public static List<string> AllKeys() {
            var _all_keys = Get<List<string>>(_KEYCOLLECTION) ?? new List<string>();

            return _all_keys; 
        }
    }

    public interface ICache
    {
        bool TryGet<T>(string key, out T data);
        T Get<T>(string key);
        bool Save<T>(string key, T data);
    }
}
